www.gusucode.com > VC++ COM组件接口Hook,COM接口挂钩-源码程序 > VC++ COM组件接口Hook,COM接口挂钩-源码程序/code/COMHook_Src/Riched20 Ver1/ImgHandler.cpp

    #include "ImgHandler.h"
#include "StdAfx.h"
#include "RichEd20.h"
#include "myRichEditOle.h"


/************************************
  REVISION LOG ENTRY
  Revision By: Zhang, Zhefu
  E-mail: codetiger@hotmail.com
  Revised on 10/2/2003  Download by http://www.NewXing.com
  Comment: This is program code accompanying "COM Interface Hooking and Its Application"
           written by Zhefu Zhang posted on www.codeguru.com 
           You are free to reuse the code on the base of keeping this comment
		   All Right Reserved by author		   
 ************************************/

#include <ocidl.h> //IPicture
#define WRITE_DISK

/*
     * Predefined Clipboard Formats
#define CF_TEXT             1
#define CF_BITMAP           2
#define CF_METAFILEPICT     3
#define CF_SYLK             4
#define CF_DIF              5
#define CF_TIFF             6
#define CF_OEMTEXT          7
#define CF_DIB              8
#define CF_PALETTE          9
#define CF_PENDATA          10
#define CF_RIFF             11
#define CF_WAVE             12
#define CF_UNICODETEXT      13
#define CF_ENHMETAFILE      14
#if(WINVER >= 0x0400)
#define CF_HDROP            15
#define CF_LOCALE           16
#define CF_MAX              17
#endif // WINVER >= 0x0400 
#define CF_OWNERDISPLAY     0x0080
#define CF_DSPTEXT          0x0081
#define CF_DSPBITMAP        0x0082
#define CF_DSPMETAFILEPICT  0x0083
#define CF_DSPENHMETAFILE   0x008E

  typedef struct tagFORMATETC 
{ 
    CLIPFORMAT      cfFormat; 
    DVTARGETDEVICE  *ptd; 
    DWORD           dwAspect; 
    LONG            lindex; 
    DWORD           tymed; 
}FORMATETC, *LPFORMATETC;

  typedef [transmit_as(long)] enum tagTYMED 
{ 
    TYMED_HGLOBAL     = 1, 
    TYMED_FILE        = 2, 
    TYMED_ISTREAM     = 4, 
    TYMED_ISTORAGE    = 8, 
    TYMED_GDI         = 16, 
    TYMED_MFPICT      = 32, 
    TYMED_ENHMF       = 64, 
    TYMED_NULL        = 0 
} TYMED; 


  // Mapping Modes 
#define MM_TEXT             1
#define MM_LOMETRIC         2
#define MM_HIMETRIC         3
#define MM_LOENGLISH        4
#define MM_HIENGLISH        5
#define MM_TWIPS            6
#define MM_ISOTROPIC        7
#define MM_ANISOTROPIC      8 //MSN

*/
void ParseDataObject(IDataObject* lpDataObject)
{
	DWORD dwCF[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
	                0x0080, 0x0081, 0x0082, 0x0083, 0x008E};
	DWORD dwTM[] = {1, 2, 4, 8, 16, 32, 64, 0};
	int dimCF = sizeof(dwCF)/sizeof(dwCF[0]);
	int dimTM = sizeof(dwTM)/sizeof(dwTM[0]);
	for(int i = 0; i < dimCF; i++)
	{
		for(int j = 0; j < dimTM; j++)
		{
			FORMATETC fm; //in
		    fm.cfFormat = dwCF[i];			// Clipboard format 
	        fm.ptd = NULL;							// Target Device = Screen
	        fm.dwAspect = DVASPECT_CONTENT;			// Level of detail = Full content
	        fm.lindex = -1;							// Index = Not applicaple
	        fm.tymed = dwTM[j];
            STGMEDIUM stgm; //out
		    HRESULT hr =  lpDataObject->GetData(&fm, &stgm);
		    if(FAILED(hr)) 
			{
				continue;
			}
			else
			{
				PopMsg(_T("%d, %d"), i, j);
			}
		}
	}
}


BOOL GeneralObjHandler(IRichEditOle* pReo)
{
	int nCount = pReo->GetObjectCount();
	for(int i = nCount-1; i >= 0; i--) //Intentional Reverse Query for Pos
	{
		REOBJECT* ro = new REOBJECT;
		ro->cbStruct = sizeof(REOBJECT);
		HRESULT hr = pReo->GetObject(i, ro, REO_GETOBJ_ALL_INTERFACES); //REO_GETOBJ_POLEOBJ); //REO_GETOBJ_ALL_INTERFACES);
		if(FAILED(hr)) 
		{
			ReportErrEx(_T("GeneralObjHandler GetObject Failed %d"), i);
			continue;
		}

		IDataObject* lpDataObject;
		//LPDATAOBJECT lpDataObject;
	    hr = (ro->poleobj)->QueryInterface(IID_IDataObject, (void **)&lpDataObject);
        if(FAILED(hr)) 
		{
			::ReportErrEx(_T("Get IID_IDataObject Failed %d"), i);
			continue;
		}
         
		STGMEDIUM stgm; //out
		FORMATETC fm; //in
		fm.cfFormat = CF_METAFILEPICT;			// Clipboard format 
	    fm.ptd = NULL;							// Target Device = Screen
	    fm.dwAspect = DVASPECT_CONTENT;			// Level of detail = Full content
	    fm.lindex = -1;							// Index = Not applicaple
	    fm.tymed = TYMED_MFPICT;

		hr =  lpDataObject->GetData(&fm, &stgm);
		if(FAILED(hr)) 
		{
			continue;
		}

		//TYMED_MFPICT: 
        //The storage medium is a metafile (HMETAFILE). Use the Windows or WIN32 functions
		//to access the metafile's data. If the STGMEDIUM punkForRelease member is NULL, 
		//the destination process should use DeleteMetaFile to delete the bitmap. 
        //hMetaFilePict
        //Metafile handle. The tymed member is TYMED_MFPICT.
        HMETAFILEPICT  hMetaFilePict = stgm.hMetaFilePict;
        LPMETAFILEPICT pMFP = (LPMETAFILEPICT) GlobalLock (hMetaFilePict);
		//PopMsg(_T("%d %d %d"), pMFP->mm, pMFP->xExt, pMFP->yExt);
		int cx = 19; //pMFP->xExt;
		int cy = 19; //pMFP->yExt;
		HWND hWnd = ::GetDesktopWindow();
		HDC hDC = ::GetDC(hWnd);
		HDC hMemDC = ::CreateCompatibleDC(hDC);
		HBITMAP hMemBmp = ::CreateCompatibleBitmap(hDC, cx, cy);
        HBITMAP hPrevBmp = (HBITMAP)::SelectObject(hMemDC, hMemBmp);
        ::PlayMetaFile(hMemDC, pMFP->hMF);
		CopyMetaFile(pMFP->hMF, _T("C:\\x.wmf")); //Just write it as WMF file
         
#ifdef WRITE_DISK
		TCHAR szIndex[32];
#ifndef _UNICODE
    sprintf(szIndex, _T("C:\\%02d"), i); 
#else
	swprintf(szIndex, _T("C:\\%02d"), i); 
#endif
		TCHAR szFilename[MAX_PATH];
		::CreateFileName(szFilename, szIndex, _T(".bmp"));
		HANDLE hFile = ::CreateFile(szFilename, GENERIC_WRITE, 0,
		        NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
	    if(hFile == INVALID_HANDLE_VALUE)
		{
			continue;
		}
		DWORD dwWritten;
#endif

		//need file header 
		BITMAPFILEHEADER bmfh;
	    bmfh.bfType = 0x4d42;  // 'BM'
		int  nColorTableEntries = 0;
	    int nSizeHdr = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * nColorTableEntries;
	    bmfh.bfSize = 0;
        bmfh.bfReserved1 = bmfh.bfReserved2 = 0;
	    bmfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) +
		   sizeof(RGBQUAD) * nColorTableEntries;	
#ifdef WRITE_DISK
		::WriteFile(hFile, (LPVOID)&bmfh, sizeof(BITMAPFILEHEADER), &dwWritten, NULL);
#endif

		BITMAP			bm;
    	// get bitmap information
		::GetObject(hMemBmp, sizeof(bm), &bm);
    	int nBitCount = bm.bmBitsPixel; //TRUE coloe ONLY!!! Warning!!!
	    BITMAPINFOHEADER* lpBMIH = (LPBITMAPINFOHEADER) new 
		  char[sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * nColorTableEntries];
 	    lpBMIH->biSize = sizeof(BITMAPINFOHEADER);
	    lpBMIH->biWidth = bm.bmWidth;
	    lpBMIH->biHeight = bm.bmHeight;
	    lpBMIH->biPlanes = 1;
	    lpBMIH->biBitCount = nBitCount;
    	lpBMIH->biCompression = BI_RGB;
	    lpBMIH->biSizeImage = 0;
	    lpBMIH->biXPelsPerMeter = 0;
	    lpBMIH->biYPelsPerMeter = 0;
	    lpBMIH->biClrUsed = nColorTableEntries;
	    lpBMIH->biClrImportant = nColorTableEntries;

		DWORD dwCount = ((DWORD) lpBMIH->biWidth * lpBMIH->biBitCount) / 32;
		if(((DWORD) lpBMIH->biWidth * lpBMIH->biBitCount) % 32) {
			dwCount++;
		}
	    dwCount *= 4;
	    dwCount = dwCount * lpBMIH->biHeight;	
        LPVOID lpImage = ::VirtualAlloc(NULL, dwCount, MEM_COMMIT, PAGE_READWRITE);
		BOOL result = GetDIBits(hMemDC, (HBITMAP)hMemBmp,
				0L,		// start scan line
				(DWORD)bm.bmHeight,	// # of scan lines
				(LPBYTE)lpImage, 			// address for bitmap bits
				(LPBITMAPINFO)lpBMIH,		// address of bitmapinfo
				(DWORD)DIB_RGB_COLORS  // use rgb for color table
	            );		

#ifdef WRITE_DISK
        ::WriteFile(hFile, lpBMIH, sizeof(BITMAPINFOHEADER), &dwWritten, NULL); 
        ::WriteFile(hFile, lpImage, dwCount, &dwWritten, NULL);
#endif
		::VirtualFree(lpImage, 0, MEM_RELEASE);

#ifdef WRITE_DISK
		::CloseHandle(hFile);
#endif	

        ::SelectObject(hMemDC, hPrevBmp);
		::DeleteObject(hMemBmp);
		::DeleteDC(hMemDC);
		::ReleaseDC(hWnd, hDC);
		::GlobalUnlock(hMetaFilePict);

		ro->poleobj->Release(); //GetObject Called AddRef so Release here
		delete ro;
	}
	return TRUE;
}